package com.lightkits.wms.domain.deliveryorder.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.lightkits.common.db.entity.BdDeliveryOrderBase;
import com.lightkits.common.db.entity.FndCustomerItem;
import com.lightkits.common.db.entity.FndPartyTl;
import com.lightkits.common.db.entity.SysFlowIndex;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.date.DateUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.framework.soa.client.id.IDServiceClient;
import com.lightkits.framework.soa.client.id.GetGlobalIDRequestType;
import com.lightkits.framework.soa.client.id.GetGlobalIDResponseType;
import com.lightkits.wms.client.DocumentServiceClient;
import com.lightkits.wms.domain.deliveryorder.model.EventParams;
import com.lightkits.wms.domain.deliveryorder.repo.FlowIIndexBdService;
import com.lightkits.wms.domain.deliveryorder.service.CreateDeliveryEventDomain;
import com.lightkits.wms.domain.deliveryorder.service.CreateDeliveryOrderDomain;
import com.lightkits.wms.domain.saveonhand.SaveOnhandExecutor;
import com.lightkits.wms.dto.deliveryorder.model.DeliveryOrderDTO;
import com.lightkits.wms.dto.document.GenerateDocNumRequestType;
import com.lightkits.wms.dto.document.GenerateDocNumResponseType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

/**
 * useParamsDomainImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/2/22 15:37
 */
@Service
public class CreateDeliveryOrderDomainImpl implements CreateDeliveryOrderDomain {
    private final FlowIIndexBdService flowIIndexBdService;
    private static final Logger LOGGER = LoggerFactory.getLogger(SaveOnhandExecutor.class);

    @Autowired
    public CreateDeliveryOrderDomainImpl(FlowIIndexBdService flowIIndexBdService, IDServiceClient idAdapterService, CreateDeliveryEventDomain createEventDomain) {
        this.flowIIndexBdService = flowIIndexBdService;
        this.idAdapterService = idAdapterService;
        this.createEventDomain = createEventDomain;
    }

    @Autowired
    private DocumentServiceClient client;

    private final CreateDeliveryEventDomain createEventDomain;

    private final IDServiceClient idAdapterService;

    /**
     * 创建发货单
     *
     * @param dto 发货单参数
     * @return
     */
    @Override
    public CheckResult<BdDeliveryOrderBase> createDeliveryOrders(DeliveryOrderDTO dto) {

        CheckResult<BdDeliveryOrderBase> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
        idRequest.setCount(1);
        GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
        Iterator<Long> sfIds = idResponse.getIds().iterator();
        BdDeliveryOrderBase deliveryOrderBase = new BdDeliveryOrderBase();
        //发货单参数校验
        IResult result = this.chackParams(dto);
        if (!result.isSuccessful()) {
            checkResult.setData(deliveryOrderBase);
            result.fill(checkResult);
            return checkResult;
        }
        try {
            GenerateDocNumRequestType request = new GenerateDocNumRequestType();
            request.setCount(1);
            request.setSize(4);
            request.setType("DLO");
            request.setField1(df.format(new Date()));
            GenerateDocNumResponseType response = client.generateDocNumber(request);

            deliveryOrderBase.setDeliveryOrderNum(response.getDocNumList().get(0));
            deliveryOrderBase.setId(sfIds.next());
            deliveryOrderBase.setOrganizationId(ParseUtil.tryLongWithException(dto.getOrgId()));
            deliveryOrderBase.setItemId(ParseUtil.tryLongWithException(dto.getItemId()));
            deliveryOrderBase.setUom(dto.getUomCode());
            deliveryOrderBase.setQty(Long.valueOf(dto.getQuantity()));
            deliveryOrderBase.setType(dto.getType());
            deliveryOrderBase.setCreateWorkerId(ParseUtil.tryLongWithException(dto.getWorkerId()));
            deliveryOrderBase.setSourceType(dto.getSourceType());
            deliveryOrderBase.setSalesOrderNum(dto.getSalesOrderNum());
            deliveryOrderBase.setCustomerAddress(dto.getCustomerAddress());
            deliveryOrderBase.setPackingType(dto.getPackingType());
            deliveryOrderBase.setPackingFormat(dto.getPackingFormat());
            deliveryOrderBase.setPackingQty(dto.getQuantity());
            deliveryOrderBase.setShippingType(dto.getShippingType());
            deliveryOrderBase.setWorkerControl(dto.getWorkerControl());
            deliveryOrderBase.setRemark(dto.getRemark());
            deliveryOrderBase.setStatus("NEW");
            if (!ObjectUtil.isNullOrEmpty(dto.getDemandId())) {
                deliveryOrderBase.setDemandId(ParseUtil.tryLongWithException(dto.getDemandId()));
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getCustomerId())) {
                deliveryOrderBase.setCustomerId(ParseUtil.tryLongWithException(dto.getCustomerId()));
                FndPartyTl customer = new FndPartyTl()
                        .selectOne(new EntityWrapper().eq(FndPartyTl.PARTY_ID, dto.getCustomerId()));
                if (!ObjectUtil.isEmpty(customer)) {
                    deliveryOrderBase.setCustomerName(customer.getPartyName());
                }
                FndCustomerItem customerItem = new FndCustomerItem()
                        .selectOne(new EntityWrapper()
                                .eq(FndCustomerItem.ORGANIZATION_ID, dto.getOrgId())
                                .eq(FndCustomerItem.ITEM_ID, dto.getItemId())
                                .eq(FndCustomerItem.CUSTOMER_ID, dto.getCustomerId()));
                if (!ObjectUtil.isEmpty(customerItem)) {
                    deliveryOrderBase.setCustomerItemId(customerItem.getId());
                    deliveryOrderBase.setCustomerItemCode(customerItem.getCustomerItem());
                }
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getCustomerDemandDate())) {
                try {
                    deliveryOrderBase.setCustomerDemandDate(DateUtil.toDate(dto.getCustomerDemandDate(), DateUtil.DEFAULT_DATE_PATTERN));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            LOGGER.error("createDeliveryOrder.error", e);
            throw new LightKitsBizException(e);
        }

        //create event
        List<BdEvent> events = new ArrayList<>();
        checkResult.setSuccessful(true);
        CheckResult<BdEvent> event = convertEvent(dto, deliveryOrderBase.getId());
        if (!event.isSuccessful() || ObjectUtil.isEmpty(event.getData())) {
            event.fill(checkResult);
            return checkResult;
        }
        events.add(event.getData());
        //create EventRecord
        deliveryOrderBase.store(events);
        checkResult.setData(deliveryOrderBase);
        return checkResult;
    }

    /**
     * 创建发货单事件
     *
     * @param dto        发货单参数
     * @param deliveryId 发货单Id
     * @return
     */
    private CheckResult<BdEvent> convertEvent(DeliveryOrderDTO dto, Long deliveryId) {
        EventParams params = new EventParams();
        params.setEventTypeCode("DELIVERY_ORDER_NEW");
        params.setKeyValue("NEW");
        params.setObjectId(deliveryId);
        params.setObjectType("DELIVERY_ORDER");
        params.setWorkerId(dto.getWorkerId());
        params.setParentEventId(dto.getParentEventId());
        params.setOrgId(dto.getOrgId());
        params.setRecordType("STATUS");
        return createEventDomain.createEvent(params);
    }

    /**
     * 事件快照的创建
     *
     * @param keyValue   事件关键值
     * @param objectId   事件对象ID
     * @param recordType 事件记录类型
     * @return
     **/
    @Override
    public BdEventRecord createEventRecord(String recordType, String keyValue, Long objectId) {

        BdEventRecord eventRecord = new BdEventRecord();
        try {
            eventRecord.setObjectId(objectId);
            eventRecord.setObjectType("DELIVERY_ORDER");
            eventRecord.setRecordType(recordType);
            eventRecord.setKeyValue(keyValue);
        } catch (Exception e) {
            LOGGER.error("createEventRecord.error", e);
            throw new LightKitsBizException(e);
        }
        return eventRecord;
    }

    /**
     * 创建发货单参数校验
     *
     * @param dto 发货单参数
     * @return
     */
    private IResult chackParams(DeliveryOrderDTO dto) {
        try {
            IntegrityValidator.begin().validate(dto.getOrgId(), "Organization Id")
                    .validate(dto.getItemId(), "Item Id")
                    .validate(dto.getWorkerId(), "Worker Id")
                    .validate(dto.getUomCode(), "Uom Code")
                    .validate(dto.getQuantity(), "Quantity")
                    .validate(dto.getSourceType(), "Source Type")
            ;
            Pattern pattern = Pattern.compile("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])");
            if (!pattern.matcher(dto.getQuantity()).matches()) {
                return IResult.fail("The Quantity is invalid");
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getCustomerDemandDate()) &&
                    !DateUtil.isDate(dto.getCustomerDemandDate(), DateUtil.DEFAULT_DATE_PATTERN)) {
                return IResult.fail("The Customer Demand  Date is invalid");
            }
        } catch (LightKitsBizException e) {
            return e.result();
        }
        return IResult.success();
    }

}
